import Layers from "../layers";

const word = ['doc', 'docx']
const excel = ['xls', 'xlsx']
const media = ['mp4', 'mp3']
const text = ['txt', 'xml', 'json', 'html', 'css', 'js']
const images = ['png', 'jpg', 'jpeg', 'ico', 'webp', 'gif']
const zips = ['zip', 'rar', '7z', 'tar', 'gz', 'bz2', 'tz', 'xz']

class FileUtils {

    /**
     * 下载文件
     *
     * @param name {string} - 文件名
     * @param url {string} - 文件地址
     */
    static download(name, url) {
        const a = document.createElement('a');
        a.style.display = 'none';
        a.href = url;
        a.download = name;

        document.body.appendChild(a);
        a.click();

        // 移除 a 标签
        setTimeout(() => {
            document.body.removeChild(a);
            window.URL.revokeObjectURL(url);
        }, 0);
    }

    /**
     * 导出字符串并另存为文件
     *
     * @param filename {string} 文件名，需要包含扩展名
     * @param content {string}     字符串数据内容
     */
    static downloadText(filename, content) {
        const blob = new Blob([content], {type: 'text/plain'});
        const url = URL.createObjectURL(blob);
        this.download(filename, url)
    }

    /**
     * 将 blob 对象作为文件下载
     *
     * @param filename {string} 文件名，需要包含扩展名
     * @param blob {Blob|File} blob 二进制文件对象
     */
    static downloadBlob(filename, blob) {
        // 创建一个指向 Blob 的 URL
        const url = URL.createObjectURL(blob);
        this.download(filename, url)
    }

    /**
     * 从 url 中还原 Blob 对象
     *
     * @param url 地址
     * @returns {Promise<Blob | void>}
     */
    static urlToBlob(url) {
        // 假设从API获取图片Blob
        return fetch(url)
            .then(response => response.blob())
            .catch(error => console.error('Error:', error));
    }

    /**
     * 将文本内容复制到剪切板
     *
     * @param content {string}     字符串数据内容
     */
    static writeTextToClipboard(content) {
        navigator.clipboard.writeText(content).then(() => {
            Layers.succeed("内容已成功复制，粘贴即可使用！")
        }).catch(err => {
            Layers.warn("浏览器不兼容，无法复制内容：", err);
        });
    }

    /**
     * 图片压缩
     *
     * 将图片宽高等比例缩小，使之刚好放在一个矩形格子内。
     *
     * @param file {Blob} 源文件
     * @return {Promise<ProgressEvent>}
     */
    static readAsDataURL(file) {
        return new Promise((resolve, reject) => {
            const reader = new FileReader();
            reader.onload = resolve;
            reader.onerror = reject;
            reader.readAsDataURL(file);
        });
    }

    /**
     * 文件转 base64
     *
     * @param file {Blob} - 文件
     * @returns {Promise<string>} - base64，E.G.：
     */
    static readAsBase64(file) {
        return this.readAsDataURL(file).then(event => event.target.result);
    }

    /**
     * 图片压缩
     *
     * 将图片宽高等比例缩小，使之刚好放在一个矩形格子内。
     *
     * @param src 源文件
     * @param width 宽
     * @param height 高
     * @return {Promise<HTMLCanvasElement>} - 画布
     */
    static scaleImage(src, width, height) {
        return new Promise((resolve, reject) => {
            const image = new Image();
            image.src = src;
            image.onload = () => {
                let w = image.width;
                let h = image.height;

                if (w > width) {
                    h *= width / w;
                    w = width;
                }

                if (h > height) {
                    w *= height / h;
                    h = height;
                }

                const canvas = document.createElement('canvas');
                canvas.width = w;
                canvas.height = h;
                const ctx = canvas.getContext('2d');
                ctx.drawImage(image, 0, 0, w, h);

                resolve(canvas);
            };
            image.onerror = reject;
        });
    }

    /**
     * 图片压缩
     *
     * 将图片宽高等比例缩小，使之刚好放在一个矩形格子内。
     *
     * @param file {Blob} 源文件
     * @param width 宽
     * @param height 高
     * @return {Promise<canvas>} - 画布
     */
    static scaleFile(file, width, height) {
        return this.readAsDataURL(file).then(event => this.scaleImage(event.target.result, width, height));
    }

    /**
     * 图片压缩
     *
     * 将图片宽高等比例缩小，使之刚好放在一个矩形格子内。
     *
     * @param src 源文件
     * @param width 宽
     * @param height 高
     * @param mini 文件输出格式
     * @param quality 图片压缩质量
     * @return {Promise<string>}
     */
    static compressImage(src, width, height, mini='image/jpg', quality = 0.7) {
        return this.scaleImage(src, width, height).then(canvas => canvas.toDataURL(mini, quality));
    }

    /**
     * 图片压缩
     *
     * 将图片宽高等比例缩小，使之刚好放在一个矩形格子内。
     *
     * @param src 源文件
     * @param width 宽
     * @param height 高
     * @param mime 文件输出格式
     * @param quality 图片压缩质量
     * @return {Promise<Blob|null>}
     */
    static compressImageAsBlob(src, width, height, mime='image/jpg', quality = 0.7) {
        return new Promise(resolve => {
            this.scaleImage(src, width, height).then(canvas => {
                canvas.toBlob(  blob => resolve(blob), mime,   quality );
            });
        })
    }

    /**
     * 构建一个文字图标
     *
     * 比如用户头像，如果用户未上传，使用用户名，构建一个临时的头像。
     *
     * @param txt {string} - 文本
     * @param font {string} - 字体
     * @param width {number} - 宽度
     * @param height {number} - 高度
     * @param max {number} - 最大比例，文字过宽自动截断
     * @param backgroundColor {string} - 背景色
     * @return {string} base64
     */
    static createFontIcon(txt, font, width = 128, height = 128, max = 0.8, backgroundColor) {
        // canvas
        let canvas = document.createElement("canvas");
        canvas.width = width;
        canvas.height = height;

        // font-size
        let ctx = canvas.getContext("2d");
        ctx.font = font;

        // 计算文字宽度，保证中文和英文都能有较好体验
        const max_width = width * max;
        if (txt.length > 4) {
            txt = txt.substring(0, 4);
        }
        if (ctx.measureText(txt).width > max_width) {
            txt = txt.substring(0, 2);
        }

        if (backgroundColor) {
            ctx.fillStyle = backgroundColor;
            ctx.fillRect(0, 0, width, height);
        }

        // 重新计算文字的位置
        const metrics = ctx.measureText(txt);
        const x = (width - metrics.width + metrics.actualBoundingBoxLeft + metrics.actualBoundingBoxRight) / 2;
        // const y = (height + metrics.actualBoundingBoxAscent + metrics.actualBoundingBoxDescent) / 2;
        const y = (height + metrics.hangingBaseline) / 2;

        ctx.fillStyle = "#ffffff";
        ctx.textAlign = "center";
        ctx.fillText(txt, x, y);
        return canvas.toDataURL('image/png');
    }

    /**
     * 获取文件扩展名
     *
     * @param filename 文件
     * @return {string|null}
     */
    static getExtension(filename) {
        if (filename == null) {
            return null;
        }
        const index = filename.lastIndexOf('.');
        if (index > 0) {
            return filename.substring(index + 1);
        } else {
            return "";
        }
    }

    /**
     * 获取文件类型
     *
     * 主要用于区分文件的阅读方式，将文件放置到对应的阅读器中，
     *
     * 如果站内安装了各种文件阅读器，可以在此调整文件类型。
     *
     * 默认通过 window.open() 的方式打开，如果浏览器支持，直接阅读文件，否则转为下载。
     *
     * @param val 扩展名
     * @returns {string}
     */
    static getFileType = (val) => {
        if (images.includes(val)) {
            // 可以设计一个相册进行查看
            return 'image';
        } else if (val === 'pdf') {
            // 可以内嵌一个 iframe 进行查看
            return 'pdf';
        } else {
            return 'file'
        }
    }


    /**
     * 区分文件的缩略图
     *
     * 这里可以增加更多文件类型
     *
     * @param val 扩展名
     * @returns {string}
     */
    static getFileIcon = (val) => {
        if (images.includes(val)) {
            return 'fa fa-fw fa-image';
        } else if (word.includes(val)) {
            return 'fa fa-fw fa-file-word-o'
        } else if (excel.includes(val)) {
            return 'fa fa-fw fa-file-excel-o'
        } else if (zips.includes(val)) {
            return 'fa fa-fw fa-file-zip-o'
        } else if (text.includes(val)) {
            return 'fa fa-fw fa-file-text-o'
        } else if (val === 'pdf') {
            return 'fa fa-fw fa-file-pdf-o'
        } else {
            return 'fa fa-fw fa-file-o'
        }
    }
}

export default FileUtils;